package cn.xing.modules.app.service.impl;

import cn.xing.common.utils.PageUtils;
import cn.xing.common.utils.Query;
import cn.xing.common.utils.ShiroUtils;
import cn.xing.modules.app.dao.SysNotificationDao;
import cn.xing.modules.app.entity.OrderEntity;
import cn.xing.modules.app.entity.SysNotificationEntity;
import cn.xing.modules.app.entity.SysNotificationReadLogEntity;
import cn.xing.modules.app.remindvo.OrderChangeVo;
import cn.xing.modules.app.service.SysNotificationReadLogService;
import cn.xing.modules.app.service.SysNotificationService;
import cn.xing.modules.sys.entity.SysUserEntity;
import cn.xing.modules.sys.service.SocketIOService;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import static cn.xing.common.constant.SocketIOConstans.ORDER_STATUS_CHANGE;


@Service("sysNotificationService")
public class SysNotificationServiceImpl extends ServiceImpl<SysNotificationDao, SysNotificationEntity> implements SysNotificationService {

    private IPage<SysNotificationEntity> page;
    private Wrapper<SysNotificationEntity> queryWrapper;
    @Autowired
    private SocketIOService socketIOService;

    @Autowired
    private SysNotificationReadLogService sysNotificationReadLogService;

    @Override
    public SysNotificationEntity getAndMarkReaded(Long id) {
        SysNotificationEntity byId = getById(id);

        // 插入 阅读日志
        SysNotificationReadLogEntity logEntity = new SysNotificationReadLogEntity();
        Long userId = ShiroUtils.getUserId();
        logEntity.setSysUserId(userId);

        logEntity.setSysNotificationId(id);
        logEntity.setReadTime(new Date());
        sysNotificationReadLogService.save(logEntity);

        return byId;
    }

    @Override
    public List<SysNotificationEntity> listMyUnread() {
        SysUserEntity currentUser = ShiroUtils.getUserEntity();

        return this.baseMapper.listMyUnread(currentUser.getUserId(), currentUser.getUsername());
    }

    @Override
    public void markAllRead() {
        Long userId = ShiroUtils.getUserId();
        Date now = new Date();

        // 先查出 我未读的
        List<SysNotificationEntity> sysNotificationEntities = listMyUnread();
        List<SysNotificationReadLogEntity> readLogEntities = new ArrayList<SysNotificationReadLogEntity>();
        // 组装，批量插入
        for (SysNotificationEntity sysNotificationEntity : sysNotificationEntities) {
            SysNotificationReadLogEntity logEntity = new SysNotificationReadLogEntity();
            logEntity.setSysUserId(userId);

            logEntity.setSysNotificationId(sysNotificationEntity.getId());
            logEntity.setReadTime(now);

            readLogEntities.add(logEntity);
        }
        if (readLogEntities.size() > 0) {
            sysNotificationReadLogService.saveBatch(readLogEntities);
        }

    }

    @Override
    @Transactional
    public void onOrderCancel(OrderEntity orderEntity) {
        onOrderChange(orderEntity, 0, "取消", false);
    }

    @Override
    public void onOrderConfirm(String orderSn) {
        onOrderChange(orderSn, 0, "用户确认收货", true);
    }

    @Override
    public void onOrderUserCancelAndRefund(OrderEntity orderEntity) {
        onOrderChange(orderEntity, 0, "用户申请取消", true);

    }


    @Override
    public void onOrderPayed(OrderEntity orderEntity) {
        onOrderChange(orderEntity, 0, "用户已支付", true);
        socketIOService.newOrderBroadCast();
    }

    /**
     * 保存，并通过socketio广播
     *
     * @param orderEntity
     * @param type
     * @param orderStatusChinese
     * @param broadCast
     */
    private void onOrderChange(OrderEntity orderEntity, int type, String orderStatusChinese, boolean broadCast) {
        String orderSn = orderEntity.getOrderSn();
        onOrderChange(orderSn, type, orderStatusChinese, broadCast);
    }

    private void onOrderChange(String orderSn, int type, String orderStatusChinese, boolean broadCast) {
        String msg = buildMsg(orderSn, orderStatusChinese);
        createSysNotification(orderSn, type, msg);
        // 广播
        if (broadCast) {
            socketIOService.broadCast(ORDER_STATUS_CHANGE, msg);
        }
    }

    /**
     * 保存
     *
     * @param orderSn
     * @param type
     * @param msg
     * @return
     */
    private void createSysNotification(String orderSn, int type, String msg) {
        SysNotificationEntity sysNotificationEntity = new SysNotificationEntity();
        sysNotificationEntity.setContent(msg);
        sysNotificationEntity.setType(type);

        OrderChangeVo orderChangeVo = new OrderChangeVo(orderSn);

        sysNotificationEntity.setParams(JSON.toJSONString(orderChangeVo));

        this.baseMapper.insert(sysNotificationEntity);
    }

    private String buildMsg(String orderSn, String orderStatusChinese) {
        return String.format("订单[%s]状态有变化：[%s]", orderSn, orderStatusChinese);
    }

    @Override
    public void onUserRequireAfterSale(String orderSn) {
        String msg = buildMsg(orderSn, "用户申请售后");
        createSysNotification(orderSn, 1, msg);
        // 广播
        socketIOService.broadCast(ORDER_STATUS_CHANGE, msg);
    }


    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<SysNotificationEntity> page = this.page(
                new Query<SysNotificationEntity>().getPage(params),
                new QueryWrapper<SysNotificationEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public PageUtils queryPageUserUnread(Map<String, Object> params) {
        IPage<SysNotificationEntity> page = this.page(
                new Query<SysNotificationEntity>().getPage(params),
                new QueryWrapper<SysNotificationEntity>(),
                ShiroUtils.getUserEntity()
        );

        return new PageUtils(page);
    }



    IPage<SysNotificationEntity>  page(IPage<SysNotificationEntity>  page, Wrapper<SysNotificationEntity> queryWrapper,SysUserEntity sysUserEntity) {
        this.page = page;
        this.queryWrapper = queryWrapper;

        return getBaseMapper().selectPage(page, queryWrapper,sysUserEntity);
    }
}